package org.iabako.shared.entity.business;

import com.google.gwt.user.client.rpc.GwtTransient;
import org.hibernate.annotations.Index;
import org.iabako.shared.entity.enumeration.ExpenseType;
import org.iabako.shared.entity.enumeration.PaymentMethod;
import org.iabako.shared.entity.user.Enterprise;
import org.iabako.shared.entity.user.User;
import org.iabako.shared.tools.GenericTools;

import javax.persistence.*;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;

/**
 * Created by jose on 04/11/14.
 */

@Entity
@Table(name = "EXPENSE")
public class Expense extends BusinessEntity implements Serializable {

    @Id
    @GeneratedValue
    @Column(name = "ID")
    private Long id;

    @Column(name = "NUMBER", nullable = false)
    @Index(name = "NUMBER")
    @NotNull
    private String number;

    @Column(name = "CATEGORY", nullable = false)
    @Index(name = "CATEGORY")
    @NotNull
    private String category;

    @Column(name = "DESCRIPTION", length = 1000)
    private String description;

    @Column(name = "TYPE", nullable = false)
    @Index(name = "TYPE")
    @Enumerated(EnumType.STRING)
    @NotNull
    private ExpenseType expenseType;

    @Column(name = "PAYMENT_DATE", nullable = false)
    @Temporal(value = TemporalType.DATE)
    private Date paymentDate;

    @Column(name = "PAYMENT_VALUE", nullable = false)
    private Double paymentValue;

    @Column(name = "TAX_PERCENT")
    @Max(100)
    private Double taxPercent;

    @Column(name = "PAYMENT_METHOD")
    @Enumerated(EnumType.STRING)
    private PaymentMethod paymentMethod;

    //Don't cascade remove action because one installmentsDefinition is used by others expenses.
    @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH})
    @JoinColumn(name = "ID_INSTALLMENTS_DEF")
    private InstallmentsDefinition installmentsDefinition;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "ID_ENTERPRISE", nullable = false)
    @GwtTransient
    private Enterprise enterprise;

    @Column(name = "EXTERNAL_LINK_NAME")
    private String externalLinkName;

    @Column(name = "EXTERNAL_LINK_URL")
    private String externalLinkUrl;

    @Column(name = "CREATION_DATE")
    @Temporal(TemporalType.TIMESTAMP)
    private Date creationDate;

    @Column(name = "LAST_MODIFICATION_DATE")
    @Temporal(TemporalType.TIMESTAMP)
    private Date lastModificationDate;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "ID_LAST_MODIFICATION_USER")
    @GwtTransient
    private User lastModificationUser;

    //For GWT client side use to avoid timezone conversions
    @Transient
    private String paymentDateString;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public ExpenseType getExpenseType() {
        return expenseType;
    }

    public void setExpenseType(ExpenseType expenseType) {
        this.expenseType = expenseType;
    }

    public Date getPaymentDate() {
        return paymentDate;
    }

    public void setPaymentDate(Date paymentDate) {
        this.paymentDate = paymentDate;
    }

    public Double getPaymentValue() {
        return paymentValue;
    }

    public void setPaymentValue(Double paymentValue) {
        this.paymentValue = paymentValue;
    }

    public Double getTaxPercent() {
        return taxPercent;
    }

    public void setTaxPercent(Double taxPercent) {
        this.taxPercent = taxPercent;
    }

    public PaymentMethod getPaymentMethod() {
        return paymentMethod;
    }

    public void setPaymentMethod(PaymentMethod paymentMethod) {
        this.paymentMethod = paymentMethod;
    }

    public InstallmentsDefinition getInstallmentsDefinition() {
        return installmentsDefinition;
    }

    public void setInstallmentsDefinition(InstallmentsDefinition installmentsDefinition) {
        this.installmentsDefinition = installmentsDefinition;
    }

    public String getPaymentDateString() {
        if (paymentDateString == null) {
            paymentDateString = GenericTools.formatDateToString(paymentDate);
        }
        return paymentDateString;
    }

    public Enterprise getEnterprise() {
        return enterprise;
    }

    public void setEnterprise(Enterprise enterprise) {
        this.enterprise = enterprise;
    }

    public void setPaymentDateString(String paymentDateString) {
        this.paymentDateString = paymentDateString;
    }

    public String getExternalLinkName() {
        return externalLinkName;
    }

    public void setExternalLinkName(String externalLinkName) {
        this.externalLinkName = externalLinkName;
    }

    public String getExternalLinkUrl() {
        return externalLinkUrl;
    }

    public void setExternalLinkUrl(String externalLinkUrl) {
        this.externalLinkUrl = externalLinkUrl;
    }

    public Date getCreationDate() {
        return creationDate;
    }

    public void setCreationDate(Date creationDate) {
        this.creationDate = creationDate;
    }

    public Date getLastModificationDate() {
        return lastModificationDate;
    }

    public void setLastModificationDate(Date lastModificationDate) {
        this.lastModificationDate = lastModificationDate;
    }

    public User getLastModificationUser() {
        return lastModificationUser;
    }

    public void setLastModificationUser(User lastModificationUser) {
        this.lastModificationUser = lastModificationUser;
    }

    @Transient
    @Override
    public void copyDatesAsString() {
        getPaymentDateString();
        return;
    }

    public static Expense getExpense(String number, String category, ExpenseType expenseType, String description,
                                     Date paymentDate, PaymentMethod paymentMethod, Double paymentValue) {
        Expense expense = new Expense();
        expense.setNumber(number);
        expense.setCategory(category);
        expense.setExpenseType(expenseType);
        expense.setDescription(description);
        expense.setPaymentDate(paymentDate);
        expense.setPaymentMethod(paymentMethod);
        expense.setPaymentValue(paymentValue);

        return expense;
    }
}
